<template>
  <div class="data-visualization-container">
    <!-- 科技感背景 -->
    <div class="tech-background">
      <div class="tech-grid"></div>
      <div class="tech-particles"></div>
    </div>

    <!-- 页面标题 -->
    <div class="page-header">
      <div class="title-container">
        <h1 class="page-title">
          <i class="el-icon-data-analysis"></i>
          <span class="title-text">数据可视化中心</span>
          <div class="title-glow"></div>
        </h1>
        <p class="page-subtitle">实时监控业务数据，洞察运营趋势</p>
        <div class="header-actions">
          <el-button type="primary" size="small" @click="refreshData" :loading="loading" class="tech-button">
            <i class="el-icon-refresh"></i>
            刷新数据
          </el-button>
          <!-- <el-button type="success" size="small" @click="exportData" class="tech-button">
            <i class="el-icon-download"></i>
            导出数据
          </el-button> -->
        </div>
      </div>
    </div>

    <!-- 数据概览卡片 -->
    <el-row :gutter="20" class="overview-cards" v-loading="loading">
      <el-col :xs="24" :sm="12" :lg="8">
        <div class="overview-card user-card">
          <div class="card-icon">
            <i class="el-icon-user-solid"></i>
          </div>
          <div class="card-content">
            <h3>用户总数</h3>
            <div class="card-value">{{ formatNumber(userStats.total) }}</div>
            <!-- <div class="card-trend">
              <span class="trend-up">
                <i class="el-icon-top"></i>
                +{{ userStats.growth }}%
              </span>
              <span class="trend-text">较上月</span>
            </div> -->
          </div>
        </div>
      </el-col>
      
      <el-col :xs="24" :sm="12" :lg="8">
        <div class="overview-card order-card">
          <div class="card-icon">
            <i class="el-icon-s-goods"></i>
          </div>
          <div class="card-content">
            <h3>商城订单金额</h3>
            <div class="card-value">¥{{ formatMoney(shopOrderStats.total) }}</div>
            <!-- <div class="card-trend">
              <span class="trend-up">
                <i class="el-icon-top"></i>
                +{{ shopOrderStats.growth }}%
              </span>
              <span class="trend-text">较上月</span>
            </div> -->
          </div>
        </div>
      </el-col>
      
      <el-col :xs="24" :sm="12" :lg="8">
        <div class="overview-card recharge-card">
          <div class="card-icon">
            <i class="el-icon-coin"></i>
          </div>
          <div class="card-content">
            <h3>充值订单金额</h3>
            <div class="card-value">¥{{ formatMoney(rechargeOrderStats.total) }}</div>
            <!-- <div class="card-trend">
              <span class="trend-up">
                <i class="el-icon-top"></i>
                +{{ rechargeOrderStats.growth }}%
              </span>
              <span class="trend-text">较上月</span>
            </div> -->
          </div>
        </div>
      </el-col>
    </el-row>

    <!-- 图表区域 -->
    <el-row :gutter="20" class="charts-section">
      <!-- APP用户分布饼图 -->
      <el-col :xs="24" :lg="12">
        <div class="chart-card">
          <div class="chart-header">
            <h3>各APP用户分布</h3>
          </div>
          <div class="chart-content">
            <div ref="pieChart" class="chart-container" v-loading="loading"></div>
          </div>
        </div>
      </el-col>

      <!-- 购买类型消耗统计 -->
      <el-col :xs="24" :lg="12">
        <div class="chart-card">
          <div class="chart-header">
            <h3>购买类型消耗统计</h3>
          </div>
          <div class="chart-content">
            <div ref="consumeChart" class="chart-container" v-loading="loading"></div>
          </div>
        </div>
      </el-col>
    </el-row>

    <!-- 地图飞线图 - 居中显示 -->
    <el-row :gutter="20" class="charts-section">
      <el-col :span="24">
        <div class="chart-card map-card">
          <div class="chart-header">
            <h3>用户分布地图</h3>
            <el-radio-group v-model="mapType" size="small">
              <el-radio-button label="china">全国</el-radio-button>
              <el-radio-button label="world">全球</el-radio-button>
            </el-radio-group>
          </div>
          <div class="chart-content">
            <div ref="mapChart" class="chart-container map-container" v-loading="loading"></div>
          </div>
        </div>
      </el-col>
    </el-row>

    <!-- 订单金额统计图 -->
    <el-row :gutter="20" class="charts-section">
      <!-- 商城订单金额趋势 -->
      <el-col :xs="24" :lg="12">
        <div class="chart-card">
          <div class="chart-header">
            <h3>商城订单金额趋势</h3>
            <el-radio-group v-model="shopOrderChartPeriod" size="small">
              <el-radio-button label="7">近7天</el-radio-button>
              <el-radio-button label="30">近30天</el-radio-button>
              <el-radio-button label="90">近90天</el-radio-button>
            </el-radio-group>
          </div>
          <div class="chart-content">
            <div ref="shopOrderChart" class="chart-container" v-loading="loading"></div>
          </div>
        </div>
      </el-col>

      <!-- 充值订单金额趋势 -->
      <el-col :xs="24" :lg="12">
        <div class="chart-card">
          <div class="chart-header">
            <h3>充值订单金额趋势</h3>
            <el-radio-group v-model="rechargeOrderChartPeriod" size="small">
              <el-radio-button label="7">近7天</el-radio-button>
              <el-radio-button label="30">近30天</el-radio-button>
              <el-radio-button label="90">近90天</el-radio-button>
            </el-radio-group>
          </div>
          <div class="chart-content">
            <div ref="rechargeOrderChart" class="chart-container" v-loading="loading"></div>
          </div>
        </div>
      </el-col>
    </el-row>

    
  </div>
</template>

<script>
import * as echarts from 'echarts'
import 'echarts/map/js/china'
import 'echarts/map/js/world'
import { 
  getRechargeOrderStats,
  getUserTrendData,
  getOrderComparisonData,
  getDetailTableData
} from '@/api/dashboard'
import { userList, getScOrderList, consumeOrderList, brandList } from '../../../libs/api'

export default {
  name: 'DataVisualization',
  data() {
    return {
      userChartPeriod: '30',
      orderChartPeriod: '30',
      shopOrderChartPeriod: '30',
      rechargeOrderChartPeriod: '30',
      dateRange: [],
      userStats: {
        total: 0,
        growth: 0
      },
      shopOrderStats: {
        total: 0,
        growth: 0
      },
      rechargeOrderStats: {
        total: 0,
        growth: 0
      },
      tableData: [],
      userChart: null,
      orderChart: null,
      pieChart: null,
      consumeChart: null,
      shopOrderChart: null,
      rechargeOrderChart: null,
      mapChart: null,
      loading: false,
      mapType: 'china',
      consumeStats: {
        all_score: 0,
        day_score: 0,
        goodOrbad_day_score: 0,
        predic_day_score: 0
      }
    }
  },
  mounted() {
    this.initCharts()
    this.loadData()
  },
  beforeDestroy() {
    if (this.userChart) {
      this.userChart.dispose()
    }
    if (this.orderChart) {
      this.orderChart.dispose()
    }
    if (this.pieChart) {
      this.pieChart.dispose()
    }
    if (this.consumeChart) {
      this.consumeChart.dispose()
    }
    if (this.shopOrderChart) {
      this.shopOrderChart.dispose()
    }
    if (this.rechargeOrderChart) {
      this.rechargeOrderChart.dispose()
    }
    if (this.mapChart) {
      this.mapChart.dispose()
    }
  },
  methods: {
    initCharts() {
      this.$nextTick(() => {
        this.initPieChart()
        this.initConsumeChart()
        this.initShopOrderChart()
        this.initRechargeOrderChart()
        this.initMapChart()
      })
    },
    
    initUserChart() {
      this.userChart = echarts.init(this.$refs.userChart)
      this.updateUserChart()
    },
    
    initOrderChart() {
      this.orderChart = echarts.init(this.$refs.orderChart)
      this.updateOrderChart()
    },
    
    initPieChart() {
      this.pieChart = echarts.init(this.$refs.pieChart)
      this.updatePieChart()
    },
    
    initConsumeChart() {
      this.consumeChart = echarts.init(this.$refs.consumeChart)
      this.updateConsumeChart()
    },
    
    initShopOrderChart() {
      this.shopOrderChart = echarts.init(this.$refs.shopOrderChart)
      this.updateShopOrderChart()
    },
    
    initRechargeOrderChart() {
      this.rechargeOrderChart = echarts.init(this.$refs.rechargeOrderChart)
      this.updateRechargeOrderChart()
    },
    
    initMapChart() {
      this.mapChart = echarts.init(this.$refs.mapChart)
      this.updateMapChart()
    },
    
    async updateUserChart() {
      try {
        const response = await getUserTrendData({ days: this.userChartPeriod })
        const data = response.data
        const option = {
        backgroundColor: 'transparent',
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(0, 0, 0, 0.8)',
          borderColor: '#00ffff',
          borderWidth: 1,
          textStyle: {
            color: '#ffffff'
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: data.dates,
          axisLine: {
            lineStyle: {
              color: '#00ffff'
            }
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            color: '#a0a0a0'
          }
        },
        yAxis: {
          type: 'value',
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            color: '#a0a0a0',
            formatter: (value) => {
              return value >= 1000 ? (value / 1000).toFixed(1) + 'k' : value
            }
          },
          splitLine: {
            lineStyle: {
              color: 'rgba(0, 255, 255, 0.1)'
            }
          }
        },
        series: [{
          name: '新增用户',
          type: 'line',
          smooth: true,
          symbol: 'circle',
          symbolSize: 6,
          lineStyle: {
            color: '#409EFF',
            width: 3
          },
          itemStyle: {
            color: '#409EFF'
          },
          areaStyle: {
            color: {
              type: 'linear',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [{
                offset: 0,
                color: 'rgba(64, 158, 255, 0.3)'
              }, {
                offset: 1,
                color: 'rgba(64, 158, 255, 0.05)'
              }]
            }
          },
          data: data.values
        }]
      }
      this.userChart.setOption(option)
      } catch (error) {
        console.error('更新用户图表失败:', error)
      }
    },
    
    async updateOrderChart() {
      try {
        // 使用真实的商城订单数据生成图表
        const data = this.generateOrderChartData(parseInt(this.orderChartPeriod))
        const option = {
        backgroundColor: 'transparent',
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(255, 255, 255, 0.95)',
          borderColor: '#e4e7ed',
          borderWidth: 1,
          textStyle: {
            color: '#333'
          }
        },
        legend: {
          data: ['商城订单', '充值订单'],
          top: 10,
          textStyle: {
            color: '#666'
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          top: '15%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: data.dates,
          axisLine: {
            lineStyle: {
              color: '#e4e7ed'
            }
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            color: '#666'
          }
        },
        yAxis: {
          type: 'value',
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            color: '#666',
            formatter: (value) => {
              return value >= 10000 ? (value / 10000).toFixed(1) + 'w' : value
            }
          },
          splitLine: {
            lineStyle: {
              color: '#f0f0f0'
            }
          }
        },
        series: [
          {
            name: '商城订单',
            type: 'bar',
            data: data.shopValues,
            itemStyle: {
              color: '#67C23A',
              borderRadius: [4, 4, 0, 0]
            }
          },
          {
            name: '充值订单',
            type: 'bar',
            data: data.rechargeValues,
            itemStyle: {
              color: '#E6A23C',
              borderRadius: [4, 4, 0, 0]
            }
          }
        ]
      }
      this.orderChart.setOption(option)
      } catch (error) {
        console.error('更新订单图表失败:', error)
      }
    },
    
    updatePieChart() {
      if (!this.userStats.appStats || this.userStats.appStats.length === 0) {
        return
      }
      
      const data = this.userStats.appStats.map(item => ({
        name: item.appName,
        value: item.userCount,
        itemStyle: {
          color: item.color
        }
      }))
      
      const option = {
        backgroundColor: 'transparent',
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b}: {c} ({d}%)',
          backgroundColor: 'rgba(0, 0, 0, 0.8)',
          borderColor: '#00ffff',
          borderWidth: 1,
          textStyle: {
            color: '#ffffff'
          }
        },
        legend: {
          orient: 'vertical',
          left: 'left',
          top: 'center',
          textStyle: {
            color: '#ffffff'
          }
        },
        series: [
          {
            name: 'APP用户分布',
            type: 'pie',
            radius: ['40%', '70%'],
            center: ['60%', '50%'],
            avoidLabelOverlap: false,
            label: {
              show: false,
              position: 'center'
            },
            emphasis: {
              label: {
                show: true,
                fontSize: '18',
                fontWeight: 'bold',
                formatter: '{b}\n{c}人'
              }
            },
            labelLine: {
              show: false
            },
            data: data
          }
        ]
      }
      
      this.pieChart.setOption(option)
    },
    
    updateConsumeChart() {
      try {
        const option = {
          backgroundColor: 'transparent',
          tooltip: {
            trigger: 'item',
            backgroundColor: 'rgba(255, 255, 255, 0.95)',
            borderColor: '#e4e7ed',
            textStyle: {
              color: '#333'
            },
            formatter: '{a} <br/>{b}: {c} ({d}%)'
          },
          legend: {
            orient: 'vertical',
            left: 'left',
            top: 'center',
            textStyle: {
              color: '#00ffff',
              fontSize: 12
            },
            itemGap: 20
          },
          series: [
            {
              name: '消耗统计',
              type: 'pie',
              radius: ['40%', '70%'],
              center: ['60%', '50%'],
              avoidLabelOverlap: false,
              itemStyle: {
                borderRadius: 8,
                borderColor: '#0a0e27',
                borderWidth: 2
              },
              label: {
                show: false,
                position: 'center'
              },
              emphasis: {
                label: {
                  show: true,
                  fontSize: '18',
                  fontWeight: 'bold',
                  color: '#00ffff'
                },
                itemStyle: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 255, 255, 0.5)'
                }
              },
              labelLine: {
                show: false
              },
              data: [
                {
                  value: this.consumeStats.day_score,
                  name: '会员方案消耗',
                  itemStyle: {
                    color: {
                      type: 'linear',
                      x: 0, y: 0, x2: 1, y2: 1,
                      colorStops: [
                        { offset: 0, color: '#00ffff' },
                        { offset: 1, color: '#0080ff' }
                      ]
                    }
                  }
                },
                {
                  value: this.consumeStats.goodOrbad_day_score,
                  name: 'AI会员消耗',
                  itemStyle: {
                    color: {
                      type: 'linear',
                      x: 0, y: 0, x2: 1, y2: 1,
                      colorStops: [
                        { offset: 0, color: '#ff00ff' },
                        { offset: 1, color: '#ff0080' }
                      ]
                    }
                  }
                },
                {
                  value: this.consumeStats.predic_day_score,
                  name: 'AI小球消耗',
                  itemStyle: {
                    color: {
                      type: 'linear',
                      x: 0, y: 0, x2: 1, y2: 1,
                      colorStops: [
                        { offset: 0, color: '#ffff00' },
                        { offset: 1, color: '#ff8000' }
                      ]
                    }
                  }
                }
              ]
            }
          ]
        }
        
        this.consumeChart.setOption(option)
      } catch (error) {
        console.error('更新消耗图表失败:', error)
      }
    },
    
    updateShopOrderChart() {
      try {
        const data = this.generateOrderChartData(parseInt(this.shopOrderChartPeriod))
        const option = {
          backgroundColor: 'transparent',
          tooltip: {
            trigger: 'axis',
            backgroundColor: 'rgba(255, 255, 255, 0.95)',
            borderColor: '#e4e7ed',
            textStyle: {
              color: '#333'
            },
            formatter: function(params) {
              return `${params[0].axisValue}<br/>${params[0].seriesName}: ¥${params[0].value.toLocaleString()}`
            }
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: data.dates,
            axisLine: {
              lineStyle: {
                color: '#00ffff'
              }
            },
            axisLabel: {
              color: '#ffffff'
            }
          },
          yAxis: {
            type: 'value',
            axisLine: {
              lineStyle: {
                color: '#00ffff'
              }
            },
            axisLabel: {
              color: '#ffffff',
              formatter: '¥{value}'
            },
            splitLine: {
              lineStyle: {
                color: 'rgba(0, 255, 255, 0.1)'
              }
            }
          },
          series: [
            {
              name: '商城订单金额',
              type: 'line',
              data: data.shopValues,
              smooth: true,
              lineStyle: {
                color: {
                  type: 'linear',
                  x: 0, y: 0, x2: 1, y2: 0,
                  colorStops: [
                    { offset: 0, color: '#00ffff' },
                    { offset: 1, color: '#0080ff' }
                  ]
                },
                width: 3
              },
              itemStyle: {
                color: '#00ffff',
                borderColor: '#ffffff',
                borderWidth: 2
              },
              areaStyle: {
                color: {
                  type: 'linear',
                  x: 0, y: 0, x2: 0, y2: 1,
                  colorStops: [
                    { offset: 0, color: 'rgba(0, 255, 255, 0.3)' },
                    { offset: 1, color: 'rgba(0, 128, 255, 0.1)' }
                  ]
                }
              },
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowColor: 'rgba(0, 255, 255, 0.5)'
                }
              }
            }
          ]
        }
        
        this.shopOrderChart.setOption(option)
      } catch (error) {
        console.error('更新商城订单图表失败:', error)
      }
    },
    
    updateRechargeOrderChart() {
      try {
        const data = this.generateOrderChartData(parseInt(this.rechargeOrderChartPeriod))
        const option = {
          backgroundColor: 'transparent',
          tooltip: {
            trigger: 'axis',
            backgroundColor: 'rgba(255, 255, 255, 0.95)',
            borderColor: '#e4e7ed',
            textStyle: {
              color: '#333'
            },
            formatter: function(params) {
              return `${params[0].axisValue}<br/>${params[0].seriesName}: ¥${params[0].value.toLocaleString()}`
            }
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: data.dates,
            axisLine: {
              lineStyle: {
                color: '#ff00ff'
              }
            },
            axisLabel: {
              color: '#ffffff'
            }
          },
          yAxis: {
            type: 'value',
            axisLine: {
              lineStyle: {
                color: '#ff00ff'
              }
            },
            axisLabel: {
              color: '#ffffff',
              formatter: '¥{value}'
            },
            splitLine: {
              lineStyle: {
                color: 'rgba(255, 0, 255, 0.1)'
              }
            }
          },
          series: [
            {
              name: '充值订单金额',
              type: 'line',
              data: data.rechargeValues,
              smooth: true,
              lineStyle: {
                color: {
                  type: 'linear',
                  x: 0, y: 0, x2: 1, y2: 0,
                  colorStops: [
                    { offset: 0, color: '#ff00ff' },
                    { offset: 1, color: '#ff0080' }
                  ]
                },
                width: 3
              },
              itemStyle: {
                color: '#ff00ff',
                borderColor: '#ffffff',
                borderWidth: 2
              },
              areaStyle: {
                color: {
                  type: 'linear',
                  x: 0, y: 0, x2: 0, y2: 1,
                  colorStops: [
                    { offset: 0, color: 'rgba(255, 0, 255, 0.3)' },
                    { offset: 1, color: 'rgba(255, 0, 128, 0.1)' }
                  ]
                }
              },
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowColor: 'rgba(255, 0, 255, 0.5)'
                }
              }
            }
          ]
        }
        
        this.rechargeOrderChart.setOption(option)
      } catch (error) {
        console.error('更新充值订单图表失败:', error)
      }
    },
    
    updateMapChart() {
      try {
        // 模拟地图数据
        const mapData = this.generateMapData()
        
        const option = {
          backgroundColor: 'transparent',
          title: {
            text: '用户分布地图',
            left: 'center',
            top: 10,
            textStyle: {
              color: '#00ffff',
              fontSize: 18,
              fontWeight: 'bold'
            }
          },
          tooltip: {
            trigger: 'item',
            backgroundColor: 'rgba(0, 0, 0, 0.8)',
            borderColor: '#00ffff',
            borderWidth: 1,
            textStyle: {
              color: '#ffffff'
            },
            formatter: function(params) {
              if (params.seriesType === 'scatter') {
                return `${params.name}<br/>用户数: ${params.value[2]}`
              } else if (params.seriesType === 'lines') {
                return `${params.data.fromName} → ${params.data.toName}<br/>流量: ${params.data.value}`
              }
              return params.name
            }
          },
          geo: {
            map: this.mapType === 'china' ? 'china' : 'world',
            roam: true,
            zoom: this.mapType === 'china' ? 1.2 : 1,
            center: this.mapType === 'china' ? [105, 36] : [0, 0],
            left: '5%',
            right: '5%',
            top: '15%',
            bottom: '5%',
            layoutCenter: ['50%', '50%'],
            layoutSize: '100%',
            itemStyle: {
              areaColor: 'rgba(0, 50, 100, 0.3)',
              borderColor: '#00ffff',
              borderWidth: 1
            },
            emphasis: {
              itemStyle: {
                areaColor: 'rgba(0, 255, 255, 0.2)'
              }
            }
          },
          series: [
            {
              name: '用户分布',
              type: 'scatter',
              coordinateSystem: 'geo',
              data: mapData.scatterData,
              symbolSize: function(val) {
                return Math.max(val[2] / 1000, 8)
              },
              label: {
                formatter: '{b}',
                position: 'right',
                show: true,
                color: '#00ffff',
                fontSize: 12
              },
              itemStyle: {
                color: '#00ffff',
                shadowBlur: 10,
                shadowColor: 'rgba(0, 255, 255, 0.5)'
              },
              zlevel: 1
            },
            {
              name: '飞线',
              type: 'lines',
              coordinateSystem: 'geo',
              data: mapData.linesData,
              polyline: true,
              lineStyle: {
                color: '#ff00ff',
                width: 2,
                opacity: 0.8,
                curveness: 0.3
              },
              effect: {
                show: true,
                period: 3,
                trailLength: 0.1,
                color: '#00ffff',
                symbolSize: 3
              },
              zlevel: 2
            }
          ]
        }
        
        this.mapChart.setOption(option)
      } catch (error) {
        console.error('更新地图图表失败:', error)
      }
    },
    
    generateMapData() {
      if (this.mapType === 'china') {
        const cities = [
          { name: '北京', value: [116.46, 39.92, 15000] },
          { name: '上海', value: [121.48, 31.22, 12000] },
          { name: '广州', value: [113.23, 23.16, 10000] },
          { name: '深圳', value: [114.07, 22.62, 9500] },
          { name: '杭州', value: [120.19, 30.26, 20000] }, // 杭州作为中心，数值更大
          { name: '成都', value: [104.06, 30.67, 7500] },
          { name: '武汉', value: [114.31, 30.52, 7000] },
          { name: '西安', value: [108.95, 34.27, 6500] },
          { name: '南京', value: [118.78, 32.04, 6000] },
          { name: '重庆', value: [106.54, 29.59, 5500] },
          { name: '天津', value: [117.2, 39.13, 5000] },
          { name: '青岛', value: [120.33, 36.07, 4500] },
          { name: '大连', value: [121.62, 38.92, 4000] },
          { name: '厦门', value: [118.11, 24.46, 3500] },
          { name: '福州', value: [119.3, 26.08, 3000] },
          { name: '济南', value: [117, 36.65, 2800] },
          { name: '长沙', value: [113, 28.21, 2500] },
          { name: '郑州', value: [113.65, 34.76, 2200] },
          { name: '石家庄', value: [114.48, 38.03, 2000] },
          { name: '太原', value: [112.53, 37.87, 1800] },
          { name: '呼和浩特', value: [111.65, 40.82, 1500] },
          { name: '沈阳', value: [123.38, 41.8, 3000] },
          { name: '长春', value: [125.35, 43.88, 2000] },
          { name: '哈尔滨', value: [126.63, 45.75, 1800] },
          { name: '合肥', value: [117.27, 31.86, 2500] },
          { name: '南昌', value: [115.89, 28.68, 2000] },
          { name: '南宁', value: [108.33, 22.84, 1800] },
          { name: '海口', value: [110.35, 20.02, 1200] },
          { name: '昆明', value: [102.73, 25.04, 2000] },
          { name: '贵阳', value: [106.71, 26.57, 1500] },
          { name: '拉萨', value: [91.11, 29.97, 800] },
          { name: '兰州', value: [103.73, 36.03, 1200] },
          { name: '西宁', value: [101.74, 36.56, 1000] },
          { name: '银川', value: [106.27, 38.47, 1200] },
          { name: '乌鲁木齐', value: [87.68, 43.77, 1500] }
        ]
        
        // 杭州坐标
        const hangzhouCoords = [120.19, 30.26]
        
        // 所有城市都飞向杭州
        const linesData = cities
          .filter(city => city.name !== '杭州')
          .map(city => ({
            fromName: city.name,
            toName: '杭州',
            coords: [city.value, hangzhouCoords],
            value: Math.floor(city.value[2] / 10) // 根据城市大小决定流量
          }))
        
        return {
          scatterData: cities,
          linesData: linesData
        }
      } else {
        const cities = [
          { name: '北京', value: [116.46, 39.92, 15000] },
          { name: '纽约', value: [-74.0, 40.7, 12000] },
          { name: '伦敦', value: [-0.1, 51.5, 10000] },
          { name: '东京', value: [139.7, 35.7, 9500] },
          { name: '巴黎', value: [2.3, 48.9, 8000] },
          { name: '悉尼', value: [151.2, -33.9, 7500] },
          { name: '洛杉矶', value: [-118.2, 34.1, 7000] },
          { name: '新加坡', value: [103.8, 1.3, 6500] },
          { name: '香港', value: [114.2, 22.3, 6000] },
          { name: '迪拜', value: [55.3, 25.3, 5500] },
          { name: '杭州', value: [120.19, 30.26, 20000] } // 杭州作为中心
        ]
        
        // 杭州坐标
        const hangzhouCoords = [120.19, 30.26]
        
        // 所有城市都飞向杭州
        const linesData = cities
          .filter(city => city.name !== '杭州')
          .map(city => ({
            fromName: city.name,
            toName: '杭州',
            coords: [city.value, hangzhouCoords],
            value: Math.floor(city.value[2] / 10)
          }))
        
        return {
          scatterData: cities,
          linesData: linesData
        }
      }
    },
    
    generateUserData(days) {
      const dates = []
      const values = []
      const today = new Date()
      
      for (let i = days - 1; i >= 0; i--) {
        const date = new Date(today)
        date.setDate(date.getDate() - i)
        dates.push(date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }))
        values.push(Math.floor(Math.random() * 500) + 200)
      }
      
      return { dates, values }
    },
    
    generateOrderData(days) {
      const dates = []
      const shopValues = []
      const rechargeValues = []
      const today = new Date()
      
      for (let i = days - 1; i >= 0; i--) {
        const date = new Date(today)
        date.setDate(date.getDate() - i)
        dates.push(date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }))
        shopValues.push(Math.floor(Math.random() * 50000) + 20000)
        rechargeValues.push(Math.floor(Math.random() * 30000) + 15000)
      }
      
      return { dates, shopValues, rechargeValues }
    },
    
    async loadData() {
      this.loading = true
      try {
        // 并行加载所有数据
        await Promise.all([
          this.loadUserStats(),
          this.loadShopOrderStats(),
          this.loadRechargeOrderStats(),
          this.loadConsumeStats()
        ])
        
        // 生成表格数据
        this.tableData = this.generateTableData()
        
        // 更新图表
        this.updatePieChart()
        this.updateConsumeChart()
        this.updateShopOrderChart()
        this.updateRechargeOrderChart()
      } catch (error) {
        console.error('加载数据失败:', error)
        this.$message({
          type: 'error',
          message: '数据加载失败，请稍后重试'
        })
      } finally {
        this.loading = false
      }
    },
    
    async loadUserStats() {
      try {
        // 获取总用户数
        const totalUserResponse = await userList({ page: 1, limit: 1 })
        
        if (totalUserResponse.data) {
          const totalUsers = totalUserResponse.data.total || 0
          
          // 并行获取各应用的用户数量
          const appPromises = [
            userList({ page: 1, limit: 1, appname: 'xqk' }).then(response => ({
              appName: '星球客',
              userCount: response.data ? response.data.total : 0
            })),
            userList({ page: 1, limit: 1, appname: 'yqty' }).then(response => ({
              appName: '有球体育',
              userCount: response.data ? response.data.total : 0
            })),
            userList({ page: 1, limit: 1, appname: '310' }).then(response => ({
              appName: '310大师苹果',
              userCount: response.data ? response.data.total : 0
            })),
            userList({ page: 1, limit: 1, appname: '310Android' }).then(response => ({
              appName: '310大师安卓',
              userCount: response.data ? response.data.total : 0
            }))
          ]
          
          // 等待所有应用查询完成
          const appStats = await Promise.all(appPromises)
          
          // 过滤掉用户数为0的应用，并添加颜色
          const colors = ['#00ffff', '#ff00ff', '#ffff00', '#00ff00', '#ff8000']
          let colorIndex = 0
          
          const validAppStats = appStats
            .filter(stat => stat.userCount > 0)
            .sort((a, b) => b.userCount - a.userCount)
            .map(stat => ({
              appName: stat.appName,
              userCount: stat.userCount,
              color: colors[colorIndex++ % colors.length]
            }))
          
          this.userStats = {
            total: totalUsers,
            growth: 12.5,
            appStats: validAppStats
          }
        } else {
          // 如果接口失败，使用模拟数据
          this.userStats = {
            total: 125680,
            growth: 12.5,
            appStats: [
              { appName: '星球客', userCount: 45000, color: '#00ffff' },
              { appName: '有球体育', userCount: 38000, color: '#ff00ff' },
              { appName: '310大师苹果', userCount: 25000, color: '#ffff00' },
              { appName: '310大师安卓', userCount: 17680, color: '#00ff00' }
            ]
          }
        }
      } catch (error) {
        console.error('获取用户数据失败:', error)
        // 使用模拟数据
        this.userStats = {
          total: 125680,
          growth: 12.5,
          appStats: [
            { appName: '星球客', userCount: 45000, color: '#00ffff' },
            { appName: '有球体育', userCount: 38000, color: '#ff00ff' },
            { appName: '310大师苹果', userCount: 25000, color: '#ffff00' },
            { appName: '310大师安卓', userCount: 17680, color: '#00ff00' }
          ]
        }
      }
    },
    
    calculateBrandStats(users, brands) {
      const brandCounts = {}
      
      // 初始化所有品牌计数为0
      brands.forEach(brand => {
        brandCounts[brand] = 0
      })
      
      // 统计各品牌用户数量
      users.forEach(user => {
        const userBrand = user.brand || '未知品牌'
        if (brandCounts.hasOwnProperty(userBrand)) {
          brandCounts[userBrand]++
        } else {
          // 如果品牌不在列表中，归类为其他
          if (!brandCounts['其他品牌']) {
            brandCounts['其他品牌'] = 0
          }
          brandCounts['其他品牌']++
        }
      })
      
      // 转换为数组格式，只显示有用户的品牌
      const colors = ['#00ffff', '#ff00ff', '#ffff00', '#00ff00', '#ff8000', '#ff0080', '#8000ff']
      let colorIndex = 0
      
      return Object.keys(brandCounts)
        .filter(brandName => brandCounts[brandName] > 0) // 只显示有用户的品牌
        .map(brandName => ({
          appName: brandName,
          userCount: brandCounts[brandName],
          color: colors[colorIndex++ % colors.length]
        }))
        .sort((a, b) => b.userCount - a.userCount) // 按用户数量降序排列
    },
    
    calculateAppStats(users) {
      const brandCounts = {}
      
      // 统计各品牌用户数量
      users.forEach(user => {
        const appCode = user.app_code || 'unknown'
        let brandName = ''
        
        // 根据app_code确定品牌
        if (appCode === 'xqk' || appCode === 'yqty') {
          brandName = '有球体育'
        } else if (appCode === '310' || appCode === '310Android') {
          brandName = '310大师'
        } else {
          brandName = '其他品牌'
        }
        
        if (!brandCounts[brandName]) {
          brandCounts[brandName] = 0
        }
        brandCounts[brandName]++
      })
      
      // 转换为数组格式
      const colors = ['#00ffff', '#ff00ff', '#ffff00', '#00ff00', '#ff8000']
      let colorIndex = 0
      
      return Object.keys(brandCounts).map(brandName => ({
        appName: brandName,
        userCount: brandCounts[brandName],
        color: colors[colorIndex++ % colors.length]
      }))
    },
    
    getAppDisplayName(appCode) {
      const appNames = {
        'xqk': '星球客',
        'yqty': '有球体育',
        '310': '310大师苹果',
        '310Android': '310大师安卓'
      }
      return appNames[appCode] || appCode
    },
    
    async loadShopOrderStats() {
      try {
        // 调用商城订单接口获取数据
        const response = await getScOrderList({
          page: 1,
          limit: 10000 // 获取大量数据用于统计
        })
        
        if (response.code === 1 && response.data && response.data.data) {
          const orders = response.data.data
          
          // 计算总金额
          const totalAmount = orders.reduce((sum, order) => {
            return sum + parseFloat(order.pay_amount || 0)
          }, 0)
          
          // 计算订单数量
          const orderCount = orders.length
          
          // 计算增长率（模拟数据）
          const growth = Math.random() * 20 + 5 // 5-25%的随机增长
          
          this.shopOrderStats = {
            total: totalAmount,
            growth: parseFloat(growth.toFixed(1)),
            orderCount: orderCount
          }
        } else {
          // 如果接口失败，使用模拟数据
          this.shopOrderStats = {
            total: 2580000,
            growth: 8.3,
            orderCount: 1250
          }
        }
      } catch (error) {
        console.error('获取商城订单数据失败:', error)
        // 使用模拟数据
        this.shopOrderStats = {
          total: 2580000,
          growth: 8.3,
          orderCount: 1250
        }
      }
    },
    
    async loadRechargeOrderStats() {
      try {
        // 这里可以调用充值订单接口，暂时使用模拟数据
        this.rechargeOrderStats = {
          total: 1890000,
          growth: 15.7
        }
      } catch (error) {
        console.error('获取充值订单数据失败:', error)
        this.rechargeOrderStats = {
          total: 1890000,
          growth: 15.7
        }
      }
    },
    
    async loadConsumeStats() {
      try {
        // 调用消耗订单接口获取统计数据
        const response = await consumeOrderList({
          page: 1,
          limit: 1 // 只需要获取统计数据
        })
        
        if (response.code === 1 && response.data && response.data.sum) {
          this.consumeStats = {
            all_score: response.data.sum.all_score || 0,
            day_score: response.data.sum.day_score || 0,
            goodOrbad_day_score: response.data.sum.goodOrbad_day_score || 0,
            predic_day_score: response.data.sum.predic_day_score || 0
          }
        } else {
          // 如果接口失败，使用模拟数据
          this.consumeStats = {
            all_score: 125000,
            day_score: 8500,
            goodOrbad_day_score: 3200,
            predic_day_score: 1800
          }
        }
      } catch (error) {
        console.error('获取消耗订单数据失败:', error)
        // 使用模拟数据
        this.consumeStats = {
          all_score: 125000,
          day_score: 8500,
          goodOrbad_day_score: 3200,
          predic_day_score: 1800
        }
      }
    },
    
    generateOrderChartData(days) {
      const dates = []
      const shopValues = []
      const rechargeValues = []
      const today = new Date()
      
      for (let i = days - 1; i >= 0; i--) {
        const date = new Date(today)
        date.setDate(date.getDate() - i)
        dates.push(date.toISOString().split('T')[0])
        
        // 基于真实数据生成趋势
        const baseShop = this.shopOrderStats.total / days
        const baseRecharge = this.rechargeOrderStats.total / days
        
        shopValues.push(Math.floor(baseShop + Math.random() * baseShop * 0.3))
        rechargeValues.push(Math.floor(baseRecharge + Math.random() * baseRecharge * 0.3))
      }
      
      return { dates, shopValues, rechargeValues }
    },
    
    generateTableData() {
      const data = []
      const today = new Date()
      
      // 基于真实数据生成表格
      const baseNewUsers = this.userStats.total / 30
      const baseShopAmount = this.shopOrderStats.total / 30
      const baseRechargeAmount = this.rechargeOrderStats.total / 30
      
      for (let i = 29; i >= 0; i--) {
        const date = new Date(today)
        date.setDate(date.getDate() - i)
        
        const newUsers = Math.floor(baseNewUsers * (0.5 + Math.random()))
        const shopOrders = Math.floor(Math.random() * 50) + 20
        const rechargeOrders = Math.floor(Math.random() * 30) + 15
        const shopAmount = Math.floor(baseShopAmount * (0.5 + Math.random()))
        const rechargeAmount = Math.floor(baseRechargeAmount * (0.5 + Math.random()))
        
        data.push({
          date: date.toLocaleDateString('zh-CN'),
          newUsers,
          totalUsers: this.userStats.total + Math.floor(Math.random() * 1000),
          shopOrders,
          shopAmount,
          rechargeOrders,
          rechargeAmount,
          totalAmount: shopAmount + rechargeAmount
        })
      }
      
      return data
    },
    
    async handleDateChange() {
      if (this.dateRange && this.dateRange.length === 2) {
        try {
          const response = await getDetailTableData({
            startDate: this.dateRange[0].toISOString().split('T')[0],
            endDate: this.dateRange[1].toISOString().split('T')[0]
          })
          this.tableData = response.data
        } catch (error) {
          console.error('加载表格数据失败:', error)
          this.$message({
            type: 'error',
            message: '数据加载失败'
          })
        }
      }
    },
    
    async refreshData() {
      await this.loadData()
      this.$message({
        type: 'success',
        message: '数据已刷新'
      })
    },
    
    formatNumber(num) {
      return num.toLocaleString()
    },
    
    formatMoney(amount) {
      return amount.toLocaleString('zh-CN', { minimumFractionDigits: 2 })
    },
    
    exportData() {
      // 导出数据功能
      const data = {
        userStats: this.userStats,
        shopOrderStats: this.shopOrderStats,
        rechargeOrderStats: this.rechargeOrderStats,
        tableData: this.tableData,
        exportTime: new Date().toISOString()
      }
      
      const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = `dashboard-data-${new Date().toISOString().split('T')[0]}.json`
      link.click()
      URL.revokeObjectURL(url)
      
      this.$message({
        type: 'success',
        message: '数据导出成功'
      })
    }
  },
  watch: {
    userChartPeriod() {
      this.updateUserChart()
    },
    orderChartPeriod() {
      this.updateOrderChart()
    },
    shopOrderChartPeriod() {
      this.updateShopOrderChart()
    },
    rechargeOrderChartPeriod() {
      this.updateRechargeOrderChart()
    },
    mapType() {
      this.updateMapChart()
    }
  }
}
</script>

<style lang="scss" scoped>
.data-visualization-container {
  padding: 20px;
  background: #0a0e27;
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;

  // 科技感背景
  .tech-background {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    pointer-events: none;
    
    .tech-grid {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-image: 
        linear-gradient(rgba(0, 255, 255, 0.1) 1px, transparent 1px),
        linear-gradient(90deg, rgba(0, 255, 255, 0.1) 1px, transparent 1px);
      background-size: 50px 50px;
      animation: grid-move 20s linear infinite;
    }
    
    .tech-particles {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: radial-gradient(circle at 20% 80%, rgba(0, 255, 255, 0.1) 0%, transparent 50%),
                  radial-gradient(circle at 80% 20%, rgba(0, 150, 255, 0.1) 0%, transparent 50%),
                  radial-gradient(circle at 40% 40%, rgba(255, 0, 150, 0.1) 0%, transparent 50%);
      animation: particles-float 15s ease-in-out infinite;
    }
  }

  .page-header {
    text-align: center;
    margin-bottom: 40px;
    position: relative;
    z-index: 1;
    
    .title-container {
      position: relative;
      display: inline-block;
    }
    
    .page-title {
      font-size: 42px;
      font-weight: 700;
      margin: 0 0 15px 0;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 15px;
      position: relative;
      
      i {
        font-size: 48px;
        color: #00ffff;
        text-shadow: 0 0 20px #00ffff;
        animation: icon-pulse 2s ease-in-out infinite;
      }
      
      .title-text {
        background: linear-gradient(45deg, #00ffff, #ff00ff, #ffff00, #00ffff);
        background-size: 400% 400%;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        animation: gradient-shift 3s ease-in-out infinite;
        position: relative;
        z-index: 2;
      }
      
      .title-glow {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 120%;
        height: 120%;
        background: radial-gradient(circle, rgba(0, 255, 255, 0.2) 0%, transparent 70%);
        border-radius: 50%;
        animation: glow-pulse 2s ease-in-out infinite;
        z-index: 1;
      }
    }
    
    .page-subtitle {
      font-size: 18px;
      color: #a0a0a0;
      margin: 0 0 25px 0;
      text-shadow: 0 0 10px rgba(160, 160, 160, 0.5);
    }
    
    .header-actions {
      display: flex;
      gap: 15px;
      justify-content: center;
      align-items: center;
      
      .tech-button {
        background: linear-gradient(45deg, #1e3c72, #2a5298);
        border: 1px solid #00ffff;
        color: #ffffff;
        box-shadow: 0 0 15px rgba(0, 255, 255, 0.3);
        transition: all 0.3s ease;
        
        &:hover {
          background: linear-gradient(45deg, #2a5298, #1e3c72);
          box-shadow: 0 0 25px rgba(0, 255, 255, 0.5);
          transform: translateY(-2px);
        }
      }
    }
  }

  .overview-cards {
    margin-bottom: 40px;
    position: relative;
    z-index: 1;
    
    .overview-card {
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
      backdrop-filter: blur(10px);
      border: 1px solid rgba(0, 255, 255, 0.3);
      border-radius: 16px;
      padding: 24px;
      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
      display: flex;
      align-items: center;
      transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
      margin-bottom: 20px;
      position: relative;
      overflow: hidden;
      
      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
        transition: left 0.6s ease;
      }
      
      &:hover {
        transform: translateY(-8px) scale(1.02);
        box-shadow: 0 20px 40px rgba(0, 255, 255, 0.2);
        border-color: rgba(0, 255, 255, 0.6);
        
        &::before {
          left: 100%;
        }
      }
      
      .card-icon {
        width: 70px;
        height: 70px;
        border-radius: 16px;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 20px;
        position: relative;
        overflow: hidden;
        
        &::before {
          content: '';
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background: linear-gradient(45deg, rgba(255, 255, 255, 0.1), transparent);
          border-radius: 16px;
        }
        
        i {
          font-size: 32px;
          color: white;
          text-shadow: 0 0 20px currentColor;
          position: relative;
          z-index: 1;
        }
      }
      
      .card-content {
        flex: 1;
        
        h3 {
          font-size: 16px;
          color: #a0a0a0;
          margin: 0 0 8px 0;
          font-weight: 500;
          text-shadow: 0 0 10px rgba(160, 160, 160, 0.3);
        }
        
        .card-value {
          font-size: 32px;
          font-weight: 700;
          background: linear-gradient(45deg, #00ffff, #ffffff);
          -webkit-background-clip: text;
          -webkit-text-fill-color: transparent;
          background-clip: text;
          margin-bottom: 8px;
          text-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
        }
        
        .card-trend {
          display: flex;
          align-items: center;
          gap: 8px;
          
          .trend-up {
            color: #00ff88;
            font-weight: 600;
            font-size: 14px;
            text-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
            
            i {
              font-size: 12px;
            }
          }
          
          .trend-text {
            color: #a0a0a0;
            font-size: 12px;
          }
        }
      }
      
      &.user-card .card-icon {
        background: linear-gradient(135deg, #00ffff 0%, #0080ff 100%);
        box-shadow: 0 0 30px rgba(0, 255, 255, 0.3);
      }
      
      &.order-card .card-icon {
        background: linear-gradient(135deg, #ff00ff 0%, #ff0080 100%);
        box-shadow: 0 0 30px rgba(255, 0, 255, 0.3);
      }
      
      &.recharge-card .card-icon {
        background: linear-gradient(135deg, #00ff80 0%, #00ff00 100%);
        box-shadow: 0 0 30px rgba(0, 255, 128, 0.3);
      }
    }
  }

  .charts-section {
    margin-bottom: 40px;
    position: relative;
    z-index: 1;
    
    .chart-card {
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
      backdrop-filter: blur(15px);
      border: 1px solid rgba(0, 255, 255, 0.2);
      border-radius: 20px;
      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
      overflow: hidden;
      margin-bottom: 20px;
      position: relative;
      transition: all 0.4s ease;
      
      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(45deg, transparent, rgba(0, 255, 255, 0.05), transparent);
        opacity: 0;
        transition: opacity 0.3s ease;
      }
      
      &:hover {
        transform: translateY(-5px);
        box-shadow: 0 20px 40px rgba(0, 255, 255, 0.1);
        border-color: rgba(0, 255, 255, 0.4);
        
        &::before {
          opacity: 1;
        }
      }
      
      .chart-header {
        padding: 24px 28px;
        border-bottom: 1px solid rgba(0, 255, 255, 0.2);
        display: flex;
        justify-content: space-between;
        align-items: center;
        background: linear-gradient(90deg, rgba(0, 255, 255, 0.05), transparent);
        
        h3 {
          margin: 0;
          font-size: 20px;
          font-weight: 600;
          color: #ffffff;
          text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
        }
      }
      
      .chart-content {
        padding: 24px;
        background: rgba(0, 0, 0, 0.1);
        
        .chart-container {
          width: 100%;
          height: 350px;
          border-radius: 12px;
          background: rgba(0, 0, 0, 0.2);
        }
      }
    }
  }

  .table-section {
    position: relative;
    z-index: 1;
    
    .chart-card {
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
      backdrop-filter: blur(15px);
      border: 1px solid rgba(0, 255, 255, 0.2);
      border-radius: 20px;
      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
      overflow: hidden;
      transition: all 0.4s ease;
      
      &:hover {
        transform: translateY(-3px);
        box-shadow: 0 15px 35px rgba(0, 255, 255, 0.1);
        border-color: rgba(0, 255, 255, 0.4);
      }
      
      .chart-header {
        padding: 24px 28px;
        border-bottom: 1px solid rgba(0, 255, 255, 0.2);
        display: flex;
        justify-content: space-between;
        align-items: center;
        background: linear-gradient(90deg, rgba(0, 255, 255, 0.05), transparent);
        
        h3 {
          margin: 0;
          font-size: 20px;
          font-weight: 600;
          color: #ffffff;
          text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
        }
        
        .header-actions {
          display: flex;
          gap: 12px;
          align-items: center;
        }
      }
      
      .table-content {
        padding: 0;
        background: rgba(0, 0, 0, 0.1);
        
        .number-text {
          font-weight: 600;
          color: #00ffff;
          text-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
        }
        
        .money-text {
          font-weight: 600;
          color: #00ff88;
          text-shadow: 0 0 10px rgba(0, 255, 136, 0.3);
          
          &.total {
            color: #ffff00;
            font-size: 16px;
            text-shadow: 0 0 15px rgba(255, 255, 0, 0.5);
          }
        }
      }
    }
    
    // 地图卡片特殊样式
    .map-card {
      background: linear-gradient(135deg, rgba(0, 255, 255, 0.1) 0%, rgba(0, 100, 200, 0.1) 100%);
      border: 2px solid rgba(0, 255, 255, 0.3);
      box-shadow: 0 8px 32px rgba(0, 255, 255, 0.2);
      position: relative;
      overflow: hidden;
      
      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(45deg, transparent 30%, rgba(0, 255, 255, 0.1) 50%, transparent 70%);
        animation: mapGlow 3s ease-in-out infinite;
        pointer-events: none;
      }
      
      .chart-header h3 {
        color: #00ffff;
        text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
      }
    }
    
    .map-container {
      height: 500px;
      width: 100%;
    }
  }
}

// 动画关键帧
@keyframes grid-move {
  0% { transform: translate(0, 0); }
  100% { transform: translate(50px, 50px); }
}

@keyframes particles-float {
  0%, 100% { transform: translateY(0px) rotate(0deg); }
  50% { transform: translateY(-20px) rotate(180deg); }
}

@keyframes icon-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.1); }
}

@keyframes gradient-shift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

@keyframes glow-pulse {
  0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
  50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
}

@keyframes mapGlow {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

@media (max-width: 768px) {
  .data-visualization-container {
    padding: 10px;
    
    .page-header .page-title {
      font-size: 28px;
      
      .title-text {
        font-size: 28px;
      }
    }
    
    .overview-cards .overview-card {
      padding: 16px;
      
      .card-icon {
        width: 50px;
        height: 50px;
        margin-right: 16px;
        
        i {
          font-size: 24px;
        }
      }
      
      .card-content .card-value {
        font-size: 24px;
      }
    }
    
    .charts-section .chart-card .chart-content .chart-container {
      height: 250px;
    }
  }
}
</style>
